const Controller = require('../prototype/Controller')
const { models } = require('../model')
const fs = require('fs')
const { uploadFileToBucket } = require('../utils/cos')

class FileStorage extends Controller {
  constructor () {
    super({ model: models.File })
  }

  /**
   * 上传文件到 Bucket
   * @param {String} bucketName
   * @param {File} file
   * @returns {Promise<{
   *   ETag:String,
   *   location:String,
   *   url:String,
   * }>}
   * @private
   */
  async _uploadFileToBucket (bucketName, file) {
    const { path, name, type, size } = file
    let uploadInfo
    try {
      uploadInfo = await uploadFileToBucket(bucketName, name, fs.createReadStream(path))
      uploadInfo.url = `https://${uploadInfo.Location}`
      this.model.insertOne({
        // File Base Info
        name: name,
        type: type,
        size: size,
        // COS
        eTag: uploadInfo.ETag,
        location: uploadInfo.Location,
        url: uploadInfo.url
      })
    } finally {
      fs.unlink(path, function (err) {
        if (err) console.error(err)
      })
    }
    return uploadInfo
  }

  uploadIcon () {
    return async (ctx) => {
      const file = ctx.request.files.file
      const uploadInfo = await this._uploadFileToBucket('workbench', file)
      ctx.wrapper.succ(uploadInfo.url)
    }
  }

  uploadBackground () {
    return async (ctx) => {
      const file = ctx.request.files.file
      const uploadInfo = await this._uploadFileToBucket('background', file)
      ctx.wrapper.succ(uploadInfo.url)
    }
  }

  uploadEditorFile (fileType) {
    const typeName = {
      image: '图片',
      audio: '音频',
      video: '视频'
    }[fileType]

    const typeReg = new RegExp(`^${fileType}/`)

    return async (ctx) => {
      const files = ctx.request.files
      if (!files) {
        throw '文件传输失败，请重新上传'
      }
      let file = files.file
      let isWangEditor = false
      // 兼容 wangEditor
      if (!file) {
        isWangEditor = true
        file = ctx.request.files[Object.keys(ctx.request.files)[0]]
      }
      if (!file) {
        throw '文件传输失败，请重新上传'
      }
      if (file.type && !typeReg.test(file.type)) {
        throw `文件不是${typeName}类型，请重新上传`
      }
      const uploadInfo = await this._uploadFileToBucket('editor', file)
      if (isWangEditor) {
        if (fileType === 'image') {
          ctx.body = {
            errno: 0,
            data: [{
              url: uploadInfo.url,
              href: uploadInfo.url,
              alt: file.name
            }]
          }
          return
        }
        if (fileType === 'video' || fileType === 'audio') {
          ctx.body = {
            errno: 0,
            data: {
              url: uploadInfo.url
            }
          }
          return
        }
      }
      return ctx.wrapper(uploadInfo.url)
    }
  }
}

module.exports = FileStorage
